/*
 * Vec.h
 *
 *	Author: stravant
 *	Description:
 *		Contains Vec2 class
 *		
 */

#ifndef VEC_H_
#define VEC_H_

#include <iostream>

template <typename T>
class Vec {
public:
	Vec(): mX(0), mY(0) {}
	Vec(T x, T y): mX(x), mY(y) {}
	Vec(const Vec& other): mX(other.mX), mY(other.mY) {}
	~Vec() {}

	Vec& operator=(const Vec& other) {
		mX = other.mX;
		mY = other.mY;
		return *this;
	}

	//arithmetic
	Vec operator+(const Vec& other) const {
		return Vec(mX + other.mX, mY + other.mY);
	}
	Vec operator-(const Vec& other) const {
		return Vec(mX - other.mX, mY - other.mY);
	}
	Vec& operator+=(const Vec& other) {
		mX += other.mX;
		mY += other.mY;
		return *this;
	}
	Vec& operator-=(const Vec& other) {
		mX -= other.mX;
		mY -= other.mY;
		return *this;
	}

	Vec operator/(T other) const {
		return Vec(mX/other, mY/other);
	}
	Vec operator*(T other) const {
		return Vec(mX*other, mY*other);
	}

	//conditional
	bool operator>(const Vec& other) const {
		return mX > other.mX && mY > other.mY;
	}
	bool operator>=(const Vec& other) const {
		return mX >= other.mX && mY >= other.mY;
	}
	bool operator<(const Vec& other) const {
		return mX < other.mX && mY < other.mY;
	}
	bool operator<=(const Vec& other) const {
		return mX <= other.mX && mY <= other.mY;
	}
	bool operator==(const Vec& other) const {
		return mX == other.mX && mY == other.mY;
	}
	bool operator!=(const Vec& other) const {
		return mX != other.mX || mY != other.mY;
	}

	//access
	T x() const {return mX; }
	T y() const {return mY; }
	Vec& set(T x, T y) {
		mX = x;
		mY = y;
		return *this;
	}

	//cast
	template <class U>
	Vec<U> to() const {
		return Vec<U>(static_cast<U>(mX), static_cast<U>(mY));
	}
private:
	T mX, mY;
};

typedef Vec<int> IVec;
typedef Vec<float> FVec;
typedef Vec<double> DVec;

template <class T>
std::ostream& operator<<(std::ostream& out, const Vec<T>& o) {
	std::cout << "Vec<" << o.x() << ", " << o.y() << ">";
	return out;
}

#endif /* VEC_H_ */
